package per.hnvcam.searchext.data.dao.impl;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import per.hnvcam.searchext.Constants;
import per.hnvcam.searchext.data.dao.RuleDAO;
import per.hnvcam.searchext.data.model.Condition;
import per.hnvcam.searchext.data.model.Config;
import per.hnvcam.searchext.data.model.Rule;

@Service("RuleDAO")
@Transactional
public class RuleDAOImpl extends BaseDAOImpl implements RuleDAO {

   @Autowired
   @Qualifier("sessionFactory")
   private SessionFactory sessionFactory;

   @SuppressWarnings("rawtypes")
   @Override
   public List listAll() {
      return getHibernateTemplate().find("from Rule");
   }

   @Override
   public Rule findById(long id) {
      @SuppressWarnings("rawtypes")
      List result = getHibernateTemplate().find("from Rule r where r.id = ?", id);
      if (result != null && result.size() > 0) {
         return (Rule) result.get(0);
      }
      return null;
   }

   @Override
   public Rule findByClass(String classifiedClass) {
      @SuppressWarnings("rawtypes")
      List result = getHibernateTemplate().find("from Rule r where r.classifiedClass = ?", classifiedClass);
      if (result != null && result.size() > 0) {
         return (Rule) result.get(0);
      }
      return null;
   }

   @SuppressWarnings("rawtypes")
   @Override
   public List findAllBaseRules() {
      List result = getHibernateTemplate().find("from Rule r where r.ruleType = ?", Rule.BASE_RULE);
      return result;
   }

   @Override
   public List findAllClassifyRules() {
      return getHibernateTemplate().find("from Rule r where r.ruleType = ?", Rule.CLASSIFY_RULE);
   }

   @Override
   public void save(Rule rule) {
      getHibernateTemplate().save(rule);
   }

   @Override
   public void saveOrUpdate(Rule rule) {
      getHibernateTemplate().saveOrUpdate(rule);
   }

   @Override
   public void bulkSave(List<Rule> rules) {
      Session session = sessionFactory.openSession();
      Transaction tx = null;
      try {
         tx = session.beginTransaction();

         for (Rule rule : rules) {
            session.save(rule);
         }

         tx.commit();
      } catch (Exception e) {
         if (tx != null) {
            tx.rollback();
         }
      } finally {
         session.close();
      }
   }

   @Override
   public void bulkSaveOrUpdate(List<Rule> rules) {
      Session session = sessionFactory.openSession();
      Transaction tx = null;
      try {
         tx = session.beginTransaction();

         for (Rule rule : rules) {
            session.saveOrUpdate(rule);
         }

         tx.commit();
      } catch (Exception e) {
         if (tx != null) {
            tx.rollback();
         }
      } finally {
         session.close();
      }
   }

   @Override
   public void updateRuleStart() {
      Session session = sessionFactory.openSession();
      Transaction tx = null;
      try {
         tx = session.beginTransaction();

         Query ruleCount = session.createQuery("select count(*) from Rule as r");
         long count = Long.parseLong(ruleCount.uniqueResult().toString());

         Query ruleStartConfig = session.createQuery("select c from Config as c where c.property = :rule_id_start");
         ruleStartConfig.setParameter("rule_id_start", Constants.RULE_ID_START);
         Config config = (Config) ruleStartConfig.uniqueResult();
         if (config == null) {
            config = new Config();
            config.setProperty(Constants.RULE_ID_START);
         }
         config.setValue(String.valueOf(count));
         session.saveOrUpdate(config);

         tx.commit();
      } catch (Exception e) {
         if (tx != null) {
            tx.rollback();
         }
      } finally {
         session.close();
      }
   }

   @Override
   public void removeAllBaseRules() {
      removeAllRules(Rule.BASE_RULE);
   }



   @Override
   public void removeAllClassifyRules() {
      removeAllRules(Rule.CLASSIFY_RULE);
   }

   private void removeAllRules(int ruleType) {
      Session session = sessionFactory.openSession();
      Transaction tx = null;
      try {
         tx = session.beginTransaction();

         Query queryBaseRules = session.createQuery("select r from Rule as r where r.ruleType = :rule_type");
         queryBaseRules.setParameter("rule_type", ruleType);
         for (Object obj : queryBaseRules.list()) {
            Rule rule = (Rule) obj;
            for (Object obj2 : rule.getConditions()) {
               Condition condition = (Condition) obj2;
               session.delete(condition);
            }
            session.delete(rule);
         }

         tx.commit();
      } catch (Exception e) {
         if (tx != null) {
            tx.rollback();
         }
      } finally {
         session.close();
      }
   }
}
